package com.wangwei.spring.rabbit;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @RabbitListener 注解的使用条件：
 *   -1、在spring容器中，托管一个RabbitListenerContainerFactory的bean（SimpleRabbitListenerContainerFactory）
 *   -2：在启动类上面加上@EnableRabbit
 *  @RabbitListener 指定queue的时候，可以使用引用变量的方式
 *
 *  @RabbitListener 支持自动声明绑定，声明之后，自动监听到对应的queue上
 *
 *  queues和bindings不能同时指定，否则报错
 *
 *  消息处理方法上，可以直接声明Message message, Channel channel，可以将这两个对象自动注入进来(测试通过)
 * Created by wangwei on 2019/10/16 0016.
 */
@Component
public class SimpleMessageHandler {
//    @RabbitListener(queues = {"sms"})
    public void handle(@Payload String body,@Header(name = "name",required = false) String name){
        System.out.println("-----------收到消息(@Header,required = false)----------");
        System.out.println(name);
        System.out.println(body);
    }
//    @RabbitListener(queues = {"sms"})
//    public void handle(@Payload String body,@Header(name = "name",defaultValue = "zhangsan") String name){
//        System.out.println("-----------收到消息(@Header)----------");
//        System.out.println(name);
//        System.out.println(body);
//    }
//    @RabbitListener(queues = {"sms"})
    public void handle(@Payload String body,@Headers Map<String,Object> headers){
        System.out.println("-----------收到消息(@Payload)----------");
        System.out.println(headers);
        System.out.println(body);
    }

//    @RabbitListener(queues = {"sms"})
    public void handle(byte[] body){
        System.out.println("-----------收到消息(byte)----------");
        System.out.println(new String(body));
    }

//    @RabbitListener(queues = {"sms"})
    public void handle(String body){
        System.out.println("-----------收到消息(String)----------");
        System.out.println(new String(body));
    }
//    @RabbitListener(queues = {"sms"})
    public void sms(Message message){
        System.out.println("-----------收到消息(Message)----------");
        System.out.println(message.getMessageProperties());
        System.out.println(new String(message.getBody()));
    }
//    @RabbitListener(queues = {"mail","weixin"})
    public void handle(Message message){
        System.out.println("-----------收到["+message.getMessageProperties().getConsumerQueue()+"]消息----------");
        System.out.println(message.getMessageProperties());
        System.out.println(new String(message.getBody()));
    }

    /**
     * 还可以使用占位符的方式指定queue
     * @param message
     */
    @RabbitListener(queues = {"${mail.queuename}","${weixin.queuename}"},containerFactory = "rabbitListenerContainerFactory")
    public String weixin(Message message, Channel channel){
        System.out.println("-----------收到["+message.getMessageProperties().getConsumerQueue()+"]消息----------");
        System.out.println(message.getMessageProperties());
        System.out.println(new String(message.getBody()));
        System.out.println("channel: "+channel);
//        try {
//            TimeUnit.SECONDS.sleep(15);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        if(message.getMessageProperties().getHeaders().get("error") == null){
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                System.out.println("消息确认成功");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                System.out.println("消息被拒绝.....");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return message.getMessageProperties().getConsumerQueue()+"~HandleSuccess";
    }

    //监听Dead Letter Exchange
    @RabbitListener(queues = {"DLEX.queue"},containerFactory = "rabbitListenerContainerFactory")
    public void dlex(Message message,Channel channel) throws Exception{
        System.out.println("-----------收到["+message.getMessageProperties().getConsumerQueue()+"]消息----------");
        System.out.println(message.getMessageProperties());
        System.out.println(new String(message.getBody()));

        //拒绝消息
        channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
        System.out.println("----------->>拒绝["+message.getMessageProperties().getConsumerQueue()+"]消息");
    }

    /**监听priority Queue**/
    @RabbitListener(queues = {"my.priority.queue"},containerFactory = "rabbitListenerContainerFactory")
    public void priorityQueue(Message message,Channel channel) throws Exception{
        System.out.println("-----------收到["+message.getMessageProperties().getConsumerQueue()+"]消息----------");
//        System.out.println(message.getMessageProperties());
        System.out.println(new String(message.getBody()));
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    /**
     * 还可以指定一个新的binding（新的exchange，新的queue），spring amqp会自动声明
     * 但要注意自动声明的条件
     * @param message
     */
    @RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "email",durable = "true"),
            exchange = @Exchange(value = "email.exchange",type = ExchangeTypes.DIRECT,durable = "true"),
            key = "emailkey")})
    public void declare(Message message){
        System.out.println("-----------收到["+message.getMessageProperties().getConsumerQueue()+"]消息----------");
        System.out.println(message.getMessageProperties());
        System.out.println(new String(message.getBody()));
    }
}
